/*
 * Created on 25/mag/07
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package it.unibo.deis.lia.mmhc.com;

import java.util.*;

import org.apache.log4j.Logger;
import org.apache.log4j.net.SocketAppender;

import it.unibo.deis.lia.location.*; //import it.unibo.deis.lia.mac.cg.niw.NetworkInterfaceProvider;
import it.unibo.deis.lia.mmhc.mpe.MobilityEstimator;
import it.unibo.deis.lia.mmhc.util.*;
import it.unibo.deis.lia.networkInterface.*;

public class ConnectorEvaluator /* extends Thread */{

	private BottomMetric bottomMetric;

	private boolean logging = it.unibo.deis.lia.networkInterface.Properties.logging; // true==>performance
																						// gathering
																						// mode
	Logger logger = Logger.getRootLogger();

	protected ConnectorEvaluator(BottomMetric newBottomMetric) {
		this.bottomMetric = newBottomMetric;
		if (logging) {
			logger
					.addAppender(new SocketAppender(
							it.unibo.deis.lia.networkInterface.Properties.ipLoggerServer,
							4545));
		}
	}

	protected void setMetric(BottomMetric newMetric) {
		this.bottomMetric = newMetric;
	}

	protected Vector<Connector> getSuitableConnectors(float mobilityDegree,
			int mobilityState, Vector<LocationOss> joints,
			Vector<GenericNetworkInterface> availableInterfaces)
			throws Exception {
		Vector<Connector> availableConnectors = new Vector<Connector>();

		for (int i = 0; i < availableInterfaces.size(); i++) {
			// System.out.println("ConnectorEvaluator: for...");
			GenericNetworkInterface gni = availableInterfaces.elementAt(i);
			System.out.println("ConnectorEvaluator: evaluating interface #" + i
					+ ": " + gni);
			if (gni instanceof IEEE80211) {
				// System.out.println("\tIEEE80211");
				IEEE80211 ieee80211 = (IEEE80211) gni;
				if (!ieee80211.isConnectorRole()) {
					Vector<NamedLocationOss> rssiList = ieee80211.getRSSIList();
					// System.out.println("\t\trssiList.size() "+rssiList.size());
					// System.out.println("\trssiList "+rssiList);
					for (int j = 0; j < rssiList.size(); j++) {
						LocationOss tempLocOss = rssiList.elementAt(j);
						BSS bssConnector = (BSS) tempLocOss;
						// TODO is not currently supported;
						// delete the "if" below when supported.
						if ((bssConnector.getEncryption() != BSS.WPA)
						/* && bssConnector.getType()==BSS.INFRASTRUCTURE */) {
							boolean isFixed;
							if (bssConnector.getType() == BSS.ADHOC)
								isFixed = false;
							else
								isFixed = true;
							Connector newConnector = new Connector(ieee80211,
									tempLocOss, (float) 0.7, (float) 0.8,
									false, isFixed, 600);
							float endurance = computeEndurance(newConnector,
									mobilityDegree, joints);
							newConnector.setEnduranceEstimation(endurance);
							availableConnectors.addElement(newConnector);
						}
					}
				}
			} else if (gni instanceof Bluetooth) {
				// System.out.println("\tBluetooth");
				Bluetooth bluetooth = (Bluetooth) gni;
				if (!bluetooth.isConnectorRole()) {
					Vector<NamedLocationOss> rssiList = bluetooth.getRSSIList();
					// System.out.println("\t\trssiList.size() "+rssiList.size());
					// System.out.println("\t\trssiList "+rssiList);
					for (int j = 0; j < rssiList.size(); j++) {
						LocationOss tempLocOss = rssiList.elementAt(j);
						Connector newConnector = new Connector(bluetooth,
								tempLocOss, (float) 0.3, (float) 0.2, true,
								false, 70);
						float endurance = computeEndurance(newConnector,
								mobilityDegree, joints);
						newConnector.setEnduranceEstimation(endurance);
						availableConnectors.addElement(newConnector);
					}
				}
			}
		}

		Vector<Connector> suitableConnectors = bottomMetric.evaluate(
				mobilityState, availableConnectors);
		if (logging) {
			for (int i = 0; i < suitableConnectors.size(); i++) {
				logger
						.info("ConnectorEvaluator.getSuitableConnectors evaluated "
								+ suitableConnectors.elementAt(i)
										.getConnectorDescription().getId());
			}
		}
		return suitableConnectors;
	}

	private float computeEndurance(Connector connector, float mobilityDegree,
			Vector<LocationOss> joints) throws Exception {
		System.out.println("\tevaluating connector: connector=" + connector
				+ " mobilityDegree=" + mobilityDegree);
		float endurance = -1;

		if (mobilityDegree == MobilityEstimator.NOT_AVAILABLE) {
			// NOTE: when the mobility estimation is not available
			// it is supposed a great mobility degree
			mobilityDegree = (float) 0.9;
		}

		if (connector.isFixed()) {
			endurance = (1 - mobilityDegree) * connector.getCoverageRange();
		} else {
			float joint = -1;
			if (joints != null) {
				// float joint=-1;
				for (int j = 0; j < joints.size() && joint == -1; j++) {
					LocationOss jointPeer = joints.elementAt(j);
					if (jointPeer.getId().equals(
							connector.getConnectorDescription().getId())) {
						joint = (float) jointPeer.getValue();
					}
				}
				// endurance=joint*connector.getCoverageRange();*/
			}
			if (joint == -1) {
				// NOTE: when the mobility estimation is not available
				// it is supposed a limited joint degree
				joint = (float) 0.2;
			}
			endurance = joint * connector.getCoverageRange();
		}
		return endurance;
	}
}
